﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace FileCompare
{
    public partial class Form1 : Form
    {
        #region Properties

        private string _OrigialProject_Path;

        public string OrigialProject_Path
        {
            get { return _OrigialProject_Path; }
            set { _OrigialProject_Path = value; }
        }
        private string _ModifiedProject_Path;

        public string ModifiedProject_Path
        {
            get { return _ModifiedProject_Path; }
            set { _ModifiedProject_Path = value; }
        }
        private string _Diference_Path;

        public string Diference_Path
        {
            get { return _Diference_Path; }
            set { _Diference_Path = value; }
        }

        #endregion

        private Dictionary<string, string> _list1 = null;
        private Dictionary<string, string> _list2 = null;
        private Dictionary<string, bool> _extensions = null;

        private DateTime DateToCompare = DateTime.MinValue;

        /// <summary>
        /// Form1
        /// </summary>
        public Form1()
        {
            InitializeComponent();

            dateTimePicker1.Enabled = rb_date.Checked;

            _list1 = new Dictionary<string, string>();
            _list2 = new Dictionary<string, string>();
            _extensions = new Dictionary<string, bool>();
        }

        /// <summary>
        /// CopyFile
        /// </summary>
        /// <param name="file"></param>
        /// <param name="filePath"></param>
        private void CopyFile(string file, string filePath)
        {
            string FileName = CutName(file);
            string[] partes = file.Split('\\');

            string incremental = string.Empty;
            incremental += Diference_Path;

            if (partes.Length > 0)
            {
                foreach (string aux in partes)
                {
                    if (aux.Equals(FileName))
                    {
                        string destPath = incremental + "\\" + FileName;

                        if (File.Exists(destPath))
                        {
                            File.Delete(destPath);
                        }

                        File.Copy(filePath, destPath);
                    }
                    else
                    {
                        incremental += "\\" + aux;

                        if (!Directory.Exists(incremental))
                        {
                            Directory.CreateDirectory(incremental);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// CutName
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        private string CutName(string path)
        {
            string[] partes = path.Split('\\');
            return partes[partes.Length - 1];
        }

        /// <summary>
        /// CompareFile
        /// </summary>
        /// <param name="fileA"></param>
        /// <param name="fileB"></param>
        /// <returns></returns>
        private bool CompareFile(FileInfo fileA, FileInfo fileB)
        {
            bool output = false;

            string A = string.Format("{0}{1}", fileA.Name, fileA.Length);
            int hashA = A.GetHashCode();

            string B = string.Format("{0}{1}", fileB.Name, fileB.Length);
            int hashB = B.GetHashCode();

            if (hashA == hashB)
            {
                output = true;

                if (cbk_verifyDate.Checked)
                {
                    if (fileA.LastWriteTime == fileA.LastWriteTime)
                    {
                        output = true;
                    }
                    else
                    {
                        output = false;
                    }
                }
            }
            else
            {
                output = false;
            }

            return output;
        }

        /// <summary>
        /// LoadDict
        /// </summary>
        /// <param name="path"></param>
        /// <param name="_dict"></param>
        /// <param name="_Path"></param>
        private void LoadDict(string path, Dictionary<string, string> _dict, string _Path)
        {
            string[] subFiles = Directory.GetFiles(path);

            for (int file = 0; file < subFiles.Length; file++)
            {
                string tmp = subFiles[file];
                string aux = tmp.Remove(0, _Path.Length);
                _dict.Add(aux, tmp);

                this.AddLog(tmp, "View");
                FileInfo fileAux = new FileInfo(subFiles[file]);
                this.AddExtension(fileAux);
            }

            string[] subFolder = Directory.GetDirectories(path);

            for (int folder = 0; folder < subFolder.Length; folder++)
            {
                LoadDict(subFolder[folder], _dict, _Path);
            }
        }

        #region Button 

        /// <summary>
        /// bnt_original_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bnt_original_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog window = new FolderBrowserDialog();

            if (window.ShowDialog() == DialogResult.OK)
            {
                OrigialProject_Path = window.SelectedPath;
                tb_original.Text = window.SelectedPath;
                AddMessageToToolStrip("Pasta Original: " + tb_original.Text);
            }
        }

        /// <summary>
        /// btn_modified_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_modified_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog window = new FolderBrowserDialog();

            if (window.ShowDialog() == DialogResult.OK)
            {
                ModifiedProject_Path = window.SelectedPath;
                tb_modified.Text = window.SelectedPath;
                AddMessageToToolStrip("Pasta Modificada: " + tb_modified.Text);
            }
        }

        /// <summary>
        /// btn_diference_Click_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_diference_Click_1(object sender, EventArgs e)
        {
            FolderBrowserDialog window = new FolderBrowserDialog();

            if (window.ShowDialog() == DialogResult.OK)
            {
                Diference_Path = window.SelectedPath;
                tb_doference.Text = window.SelectedPath;
                AddMessageToToolStrip("Pasta Destino: " + tb_doference.Text);
            }
        }

        /// <summary>
        /// btn_clean_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_clean_Click(object sender, EventArgs e)
        {
            try
            {
                CleanList();

                OrigialProject_Path = string.Empty;
                ModifiedProject_Path = string.Empty;
                Diference_Path = string.Empty;

                tb_doference.Text = string.Empty;
                tb_modified.Text = string.Empty;
                tb_original.Text = string.Empty;

                cbk_open.Checked = false;
                cbk_verifyDate.Checked = false;
            }
            catch (Exception ex) 
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        /// <summary>
        /// Clean All list - Bug-#001-2011-07-22
        /// Clean List 1
        /// Clean List 2
        /// Clean ListView
        /// </summary>
        private void CleanList()
        {
            _list1.Clear();
            _list2.Clear();
            listView1.Items.Clear();
        }

        /// <summary>
        /// btn_check_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_check_Click(object sender, EventArgs e)
        {
            CleanList();

            if (tb_doference.Text.Equals(string.Empty) || tb_modified.Text.Equals(string.Empty) || (tb_original.Text.Equals(string.Empty) && rb_solution.Checked))
            {
                #region Check Fields

                string message = string.Empty;

                if (tb_doference.Text.Equals(string.Empty))
                {
                    message += " - Pasta destino em falta\r\n";
                }

                if (tb_modified.Text.Equals(string.Empty))
                {
                    message += " - Pasta modificada em falta\r\n";
                }

                if (tb_original.Text.Equals(string.Empty) && rb_solution.Checked)
                {
                    message += " - Pasta de origem em falta\r\n";
                }
                else if (tb_original.Text.Equals(string.Empty) && rb_date.Checked)
                {
                    AddMessageToToolStrip("Data definida: " + dateTimePicker1.Value);
                }

                MessageBox.Show(message, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Error);

                #endregion
            }
            else
            {
                if (rb_solution.Checked)
                {
                    this.LoadDict(OrigialProject_Path, _list1, OrigialProject_Path);
                }
                else
                {
                    if (DateToCompare == DateTime.MinValue)
                    {
                        DateToCompare = dateTimePicker1.Value;
                        AddMessageToToolStrip("Data definida: " + dateTimePicker1.Value);
                    }
                }

                this.LoadDict(ModifiedProject_Path, _list2, ModifiedProject_Path);

                CheckExtension window = new CheckExtension(_extensions);

                if (window.ShowDialog() == DialogResult.OK)
                {
                    List<string> Cheked = window.ListChecked;

                    #region ProgressBar
                    ProgressBar.Visible = true;
                    ProgressBar.Minimum = 0;
                    ProgressBar.Maximum = _list2.Count;
                    ProgressBar.Style = ProgressBarStyle.Blocks;
                    int count = 0;
                    #endregion

                    foreach (KeyValuePair<string, string> aux in _list2)
                    {
                        count++;
                        ProgressBar.Value = count;

                        FileInfo fileA = new FileInfo(aux.Value);
                        
                        if (rb_solution.Checked)
                        {
                            if (_list1.ContainsKey(aux.Key))
                            {
                                string _value = _list1[aux.Key];
                                FileInfo fileB = new FileInfo(_value);

                                bool equal = this.CompareFile(fileA, fileB);

                                if (!equal)
                                {
                                    if (Cheked.Contains(fileA.Extension))
                                    {
                                        this.AddLog(aux.Value, "Modified");
                                        this.CopyFile(aux.Key, aux.Value);
                                    }
                                }
                            }
                            else
                            {
                                if (Cheked.Contains(fileA.Extension))
                                {
                                    this.AddLog(aux.Value, "Modified");
                                    this.CopyFile(aux.Key, aux.Value);
                                }
                            }
                        }
                        else
                        {
                            if (fileA.LastWriteTime >= DateToCompare)
                            {
                                if (Cheked.Contains(fileA.Extension))
                                {
                                    this.AddLog(aux.Value, "Modified");
                                    this.CopyFile(aux.Key, aux.Value);
                                }
                            }
                        }
                    }

                    if (cbk_open.Checked)
                    {
                        System.Diagnostics.Process prc = new System.Diagnostics.Process();
                        prc.StartInfo.FileName = Diference_Path;
                        prc.Start();
                    }
                }
                else
                {
                    MessageBox.Show("Operação Cancelada", string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }

            ProgressBar.Value = 0;
            ProgressBar.Visible = false;
        }

        /// <summary>
        /// closeToolStripMenuItem_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        /// <summary>
        /// aboutToolStripMenuItem_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            About window = new About();
            window.Show();
        }

        /// <summary>
        /// AddLog
        /// </summary>
        /// <param name="message"></param>
        /// <param name="Action"></param>
        private void AddLog(string message, string Action)
        {
            AddMessageToToolStrip(Action + " - " + message);
            ListViewItem item = new ListViewItem();

            switch (Action)
            {
                case "View":
                    {
                        item = new ListViewItem(message);
                        item.SubItems.Add(Action);
                    } break;
                case "Modified":
                    {
                        item = new ListViewItem(message);
                        item.SubItems.Add(Action);

                        item.BackColor = Color.Red;
                        item.ForeColor = Color.White;
                    } break;
            }

            listView1.Items.Add(item);
        }

        /// <summary>
        /// AddExtension
        /// </summary>
        /// <param name="file"></param>
        private void AddExtension(FileInfo file)
        {
            try
            {
                if (!_extensions.ContainsKey(file.Extension))
                {
                    _extensions.Add(file.Extension, true);
                }
            }
            catch (Exception ex) 
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// rb_solution_CheckedChanged
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rb_solution_CheckedChanged(object sender, EventArgs e)
        {
            bnt_original.Enabled = rb_solution.Checked;
            dateTimePicker1.Enabled = !rb_solution.Checked;
        }

        /// <summary>
        /// btn_defineDate_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_defineDate_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Verifar alterções após: " + dateTimePicker1.Value, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.Information) == DialogResult.OK)
            {
                DateToCompare = dateTimePicker1.Value;
                AddMessageToToolStrip("Data definida: " + dateTimePicker1.Value);
            }
        }

        /// <summary>
        /// AddMessageToToolStrip
        /// </summary>
        /// <param name="mgs"></param>
        private void AddMessageToToolStrip(string mgs)
        {
            lb_MenuStrip.Text = mgs;
        }

        /// <summary>
        /// listView1_MouseDoubleClick
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.AddMessageToToolStrip(listView1.SelectedItems[0].Text);
        }

        /// <summary>
        /// webServiceTesterToolStripMenuItem_Click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void webServiceTesterToolStripMenuItem_Click(object sender, EventArgs e)
        {
            fm_wsTester windows = new fm_wsTester();
            windows.ShowDialog();
        }
    }
}
